﻿using System;
using System.Text;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis;

var type = CacheType.Redis;
if (type == CacheType.Memory)
{
    var cache = new ServiceCollection()
    .AddMemoryCache()
    .BuildServiceProvider()
    .GetRequiredService<IMemoryCache>();

    for (int index = 0; index < 5; index++)
    {
        Console.WriteLine(GetCurrentTime());
        await Task.Delay(1000);
    }

    DateTimeOffset GetCurrentTime()
    {
        if (!cache.TryGetValue<DateTimeOffset>("CurrentTime", out var currentTime))
        {
            cache.Set("CurrentTime", currentTime = DateTimeOffset.UtcNow);
        }
        return currentTime;
    }
}

else if (type == CacheType.Redis)
{
    var cache = new ServiceCollection().AddDistributedRedisCache(options =>
    {
        options.Configuration = "localhost";
        options.InstanceName = "Net07";
        //options.ConfigurationOptions = new ConfigurationOptions {DefaultDatabase = 3 }; // db3
    })
        .BuildServiceProvider().GetRequiredService<IDistributedCache>();
    for (int index = 0; index < 5; index++)
    {
        Console.WriteLine(await GetCurrentTimeAsync());
        await Task.Delay(1000);
    }

    async Task<DateTimeOffset> GetCurrentTimeAsync()
    {
        var key = "CurrentTime";
        var timeLiteral = await cache.GetStringAsync(key);
        if (string.IsNullOrEmpty(timeLiteral))
        {
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) // 30分钟
            };
            await cache.SetStringAsync(key, timeLiteral = DateTimeOffset.Now.ToString(), options);
        }
        return DateTimeOffset.Parse(timeLiteral);
    }
}
else if (type == CacheType.SqlServer)
{
    // 仅为demo，实际使用web
    var host = Host.CreateDefaultBuilder()
        .ConfigureHostConfiguration(a =>
        {

        }).ConfigureServices(svcs => svcs.AddDistributedSqlServerCache(options =>
        {
            options.ConnectionString = "server=.;database=demo;uid=sa;pwd=123";
            options.SchemaName = "dbo";
            options.TableName = "AspnetCache";
        })).Build();

    await GetRun(host.Services);
    host.Run();


    async Task GetRun(IServiceProvider serviceProvider)
    {
        var cache = serviceProvider.GetRequiredService<IDistributedCache>();
        var currentTime = await cache.GetStringAsync("CurrentTime");
        if (null == currentTime)
        {
            currentTime = DateTime.Now.ToString();
            await cache.SetAsync("CurrentTime", Encoding.UTF8.GetBytes(currentTime));
        }
        Console.WriteLine($"{currentTime}({DateTime.Now})");
    }
}

enum CacheType
{
    Memory,
    Redis,
    SqlServer
}